#!/usr/bin/perl -w
use strict;
use Getopt::Long;
use sort 'stable';
#use Data::Dump qw(dump);


#88888888888888888888888888888888888888888888888888888888888888888888888888888888

#	Usage

#88888888888888888888888888888888888888888888888888888888888888888888888888888888

my $usage = <<'USAGE';

USAGE:

    qstat.pl
				[--sort qdj]
				[--user user1,user2]
				[--user user3]
				q = sort by queue
				d = sort by date
				j = sort by jobs
				capital letter = sort in reverse order
				(can be applied in succession:
				 e.g. --sort Dqj = sort by reverse date then by queue then by job name)
USAGE


#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

#	Get options

#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
# mandatory

# optional parameters
my $sort = '';
my $help;
my @owners;

           

GetOptions(	'user=s'			=> \@owners,
			'sort=s'			=> \$sort,
			'help'				=> \$help);

# allow owners to be joined by commas
@owners = split(/,/, join(',',@owners)) if @owners;
my %owners;
@owners{@owners}= ();

die $usage if ($help);

$sort =~ tr/qjdQJD/012345/cd;
$sort =~ tr/qjdQJD/012345/d;
my @sort_order = split //, $sort;





my @lines = `qstat -u "*" -xml -pri`;

my $job_state = '';
my $job_name = '';
my $owner = '';
my $start_time = '';
my $queue_name = '';
my $priority = 0;
my $slots = '';
my %jobs;
for (@lines)
{
	if (/job_list state="(.*)"/)
	{
		$job_state = $1;
	}
	elsif(/<JB_name>(.*)</)
	{
		$job_name = $1;
	}
	elsif (/<JB_owner>(.*)</)
	{
		$owner = $1;
	}
	elsif (/<JAT_start_time>(.*)</)
	{
		$start_time = $1;
	}
	elsif (/<JB_priority>(.*)</)
	{
		$priority = $1;
	}
	elsif (/<JB_submission_time>(.*)</)
	{
		$start_time = $1;
	}
	elsif (/<state>S<\/state>/)
	{
		$job_state = "SUSPENDED";
	}
	elsif (/<queue_name>(.*)</)
	{
		$queue_name = $1;
	}
	elsif (/<\/job_list>/)
	{
		if (!@owners || exists $owners{$owner})
		{
			push(@{$jobs{$job_state}{$owner}}, [$queue_name, $job_name, $start_time, $priority]);
		}
	}
}

sub sort_owner
{
	my %owners;
	@owners{@_} = ();
	my @results;
	if (exists $owners{'lg'})
	{
		push(@results, 'lg');
		delete($owners{'lg'});
	}
	push(@results,  sort keys %owners);
	return @results;
}
sub sort_state
{
	my %state;
	@state{@_} = ();
	my @results;
	if (exists $state{'running'})
	{
		push(@results, 'running');
		delete($state{'running'});
	}
	if (exists $state{'pending'})
	{
		push(@results, 'pending');
		delete($state{'pending'});
	}
	push(@results,  sort keys %state);
	return @results;
}


sub sort_order(\@\@)
{
	my ($sortcommands,  $jobs) = @_;
	my @sort_names = qw(queue date job);
	for my $sort_command (reverse @$sortcommands)
	{
		if ($sort_command > 2)
		{
			$sort_command -=3;
			@$jobs = sort{$b->[$sort_command] cmp $a->[$sort_command]} @$jobs;
		}
		else
		{
			@$jobs = sort{$a->[$sort_command] cmp $b->[$sort_command]} @$jobs;
		}
	}
	return @$jobs;
}
for my $state(sort_state keys %jobs)
{
	print uc ($state). " jobs:\n";
	my $job_state = $jobs{$state};
	
	for my $owner(sort_owner keys %$job_state)
	{
		my $job_owner = $job_state->{$owner};
		print "    ", "_" x 50, "\n";
		print "    Jobs for $owner :\n";
		print "    ", "_" x 50, "\n";
		my $job_cnt = 1;
		for my $job(sort_order(@sort_order, @$job_owner))
		{
			my ($queue_name, $job_name, $start_time, $priority) = @$job;
			printf "    %3d %s\n",  $job_cnt, "$queue_name\t$start_time\t$job_name\t($priority)";
			++$job_cnt;
		}
	}
	print "    ", "8" x 50, "\n\n";
}


